﻿Imports System.ServiceModel
Imports System.ServiceModel.Configuration
Imports System.Configuration
Imports System.Xml
Imports Mystery.DbConnection
Imports System.Reflection
Imports System.IO
Imports System.Security.Cryptography
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary

''' <summary>
''' carefull at the moment is giving full control
''' </summary>
''' <remarks></remarks>
Public MustInherit Class NetContentDispatcher
    Inherits BaseEncryptedService

    Dim cd As IContentDispatcher = getGlobalObject(Of IContentDispatcher)()

    Private _content_type_map As New Dictionary(Of String, IContentXml)
    Private _xmler_map As New Dictionary(Of Type, IContentXml)
    Private _name_map As New Dictionary(Of String, Type)
    Private _getByFilter_map As New Dictionary(Of String, IFilterHelper)

    Public Interface IFilterHelper
        Function getThem(cd As IContentDispatcher, filter As IContent) As IEnumerable(Of IContent)
        Function getRefences(cd As IContentDispatcher) As IEnumerable(Of LightContentReferece)
    End Interface

    Public Class FilterHelper(Of T As IContent)
        Implements IFilterHelper


        Public Function getThem(cd As IContentDispatcher, filter As T) As IEnumerable(Of T)
            Return cd.getAllByFilter(Of T)(filter)
        End Function

        Public Function getThem1(cd As IContentDispatcher, filter As IContent) As System.Collections.Generic.IEnumerable(Of IContent) Implements IFilterHelper.getThem
            Dim result As New List(Of IContent)(getThem(cd, filter))
            Return result
        End Function

        Public Function getRefences(cd As IContentDispatcher) As System.Collections.Generic.IEnumerable(Of LightContentReferece) Implements IFilterHelper.getRefences
            Return cd.getLightContentRereferece(Of T)()
        End Function
    End Class

    Public Sub New(name As String)
        MyBase.New(name)
        Console.WriteLine("NetContentDispatcher instancing")

        For Each Type As Type In getMystery.AssemblyRegister.getTypesMarkedWith(Of ContentType)()
            Dim attr As ContentType = getMystery.AssemblyRegister.getMysteryClassAttribute(Of ContentType)(Type)
            _content_type_map(attr.name) = Type.getMysteryAttribute(Of ContentXmlAttr)().getXmler
            _xmler_map(Type) = _content_type_map(attr.name)
            _name_map(attr.name) = Type
            Dim helper_type As Type = GetType(FilterHelper(Of )).MakeGenericType(Type)
            _getByFilter_map(attr.name) = Activator.CreateInstance(helper_type)
        Next

        Me.registerHandler(Of getAllByFilterInput, getAllByFilterOutPut)(AddressOf getAllByFilter)
        Me.registerHandler(Of getAllByTypeInput, getAllByTypeOutPut)(AddressOf getAllByType)
        Me.registerHandler(Of getContentInput, getContentOutPut)(AddressOf getContent)
        Me.registerHandler(Of addContentInput)(AddressOf addContent)
        Me.registerHandler(Of containsTypeInput, containsTypeOutPut)(AddressOf containsType)
        Me.registerHandler(Of removeContentInput)(AddressOf removeContent)
        Me.registerHandler(Of createContentInput, createContentOutput)(AddressOf createContent)
        Me.registerHandler(Of getLightReferenceInput, getLightReferenceOutput)(AddressOf getLightReference)
        Me.registerHandler(Of getFileInput, getFileOutput)(AddressOf getFile)
        Me.registerHandler(Of getFilePieceInput, getFilePieceOutput)(AddressOf getFilePiece)
        Me.registerHandler(Of getSearchResultInput, getSearchResultOutput)(AddressOf search)

    End Sub

    Public Function getAllByFilter(input As getAllByFilterInput) As getAllByFilterOutPut
        Console.WriteLine("NetContentDispatcher getAllByFilter")
        Dim result As New getAllByFilterOutPut
        If input Is Nothing Then Return result
        If String.IsNullOrEmpty(input.doc) Then Return result
        Dim doc As New XmlDocument
        doc.InnerXml = input.doc

        Dim xmlelement As XmlElement = doc.FirstChild
        Dim content_type_name As String = xmlelement.Name

        Dim helper_filter As IFilterHelper = _getByFilter_map(content_type_name)
        Dim xmler As IContentXml = _content_type_map(content_type_name)
        Dim filter As IContent = xmler.readAsFilter(doc)
        Dim contents As IEnumerable(Of IContent) = helper_filter.getThem(cd, filter)

        result.docs = New List(Of String)(From x As IContent In contents Select xmler.generate(x).InnerXml)

        Return result
    End Function

    Public Function getAllByType(input As getAllByTypeInput) As getAllByTypeOutPut
        Dim result As New getAllByTypeOutPut
        If input Is Nothing Then Return result
        If String.IsNullOrEmpty(input.content_type_name) Then Return result
        Console.WriteLine("NetContentDispatcher getAllByType " & input.content_type_name)
        Dim conn As IConnection = getGlobalObject(Of IConnection)()
        Dim dt As DataTable = conn.executeQuery("select * from contents where content_type=@content_type", New SqlClient.SqlParameter("content_type", input.content_type_name))
        result.guids = New List(Of String)(From x As DataRow In dt.Rows Select CStr(x("guid")))
        Return result
    End Function

    Public Function getContent(input As getContentInput) As getContentOutPut
        Dim result As New getContentOutPut
        If input Is Nothing Then Return result
        Console.WriteLine("NetContentDispatcher getContent  " & input.guid)
        Dim guid_string As String = input.guid
        If String.IsNullOrEmpty(guid_string) Then Return result
        Dim content_guid As Guid = Guid.Empty
        If Not Guid.TryParse(guid_string, content_guid) Then Return result
        If content_guid = Guid.Empty Then Return result
        Dim c As IContent = cd.getContent(Of IContent)(content_guid)
        If c Is Nothing Then Return result
        Dim type As Type = c.GetType
        Dim xmler As IContentXml = _xmler_map(type)
        result.doc = xmler.generate(c).InnerXml

        Return result

    End Function

    Public Sub addContent(input As addContentInput)
        If input Is Nothing Then Exit Sub
        If String.IsNullOrEmpty(input.doc) Then Exit Sub
        Dim doc As New XmlDocument
        doc.InnerXml = input.doc
        Dim xmlelement As XmlElement = doc.FirstChild
        Dim content_type_name As String = xmlelement.Name
        Console.WriteLine("NetContentDispatcher addContent  " & content_type_name)
        Dim content As IContent = _content_type_map(content_type_name).read(doc)
        cd.Add(content)
    End Sub

    Public Function containsType(input As containsTypeInput) As containsTypeOutPut
        Dim result As New containsTypeOutPut
        If input Is Nothing Then Return result
        If String.IsNullOrEmpty(input.content_type_name) Then Return result
        Console.WriteLine("NetContentDispatcher containsType  " & input.content_type_name)
        result.it_does = _name_map.ContainsKey(input.content_type_name) 'sorry dude in the net the anszer is yes if I know it
        Return result
    End Function

    Public Sub removeContent(input As removeContentInput)
        Console.WriteLine("NetContentDispatcher removeContent  " & input.guid)
        cd.Remove(cd.getContent(Of IContent)(Guid.Parse(input.guid)))
    End Sub

    Public Function createContent(input As createContentInput) As createContentOutput
        Dim content_type_name As String = input.content_type_name
        Console.WriteLine("NetContentDispatcher createContent  " & content_type_name)
        Dim c_type As Type = _name_map(content_type_name)
        Dim cc As IGlobalContentCreator = getGlobalObject(Of IGlobalContentCreator)()
        Dim xmler As IContentXml = _xmler_map(c_type)
        Dim result As New createContentOutput
        result.doc = xmler.generate(cc.getNewContent(c_type)).InnerXml
        Return result
    End Function

    Public Function getLightReference(input As getLightReferenceInput) As getLightReferenceOutput
        Console.WriteLine("NetContentDispatcher getLightReference  " & input.content_type_name)
        Dim content_type_name As String = input.content_type_name
        Dim result As New getLightReferenceOutput
        Dim ct_type As Type = _name_map(content_type_name)
        result.references = New List(Of LightContentReferece)(_getByFilter_map(content_type_name).getRefences(cd))
        Return result
    End Function

    Private file_map As New Dictionary(Of String, List(Of String))
    Private file_truck_leght As Integer = 5000

    Public Function getFile(input As getFileInput) As getFileOutput
        Console.WriteLine("NetContentDispatcher getFile  " & input.guid)
        Dim fc As FileContent = cd.getContent(Of FileContent)(Guid.Parse(input.guid))
        Dim result As New getFileOutput
        Dim stremreader As New FileStream(cd.getFile(fc).FullName, FileMode.Open)
        result.lenght = stremreader.Length
        Dim bytes(stremreader.Length - 1) As Byte
        stremreader.Read(bytes, 0, stremreader.Length)
        Dim base64 As String = bytes.getBase64
        file_map(result.buffer_guid) = New List(Of String)
        While base64.Length > file_truck_leght
            file_map(result.buffer_guid).Add(base64.Substring(0, file_truck_leght))
            base64 = base64.Substring(file_truck_leght)
        End While
        file_map(result.buffer_guid).Add(base64)
        result.pieces = file_map(result.buffer_guid).Count
        stremreader.Close()
        Return result
    End Function

    Public Function getFilePiece(input As getFilePieceInput) As getFilePieceOutput
        Console.WriteLine("NetContentDispatcher getFile  " & input.piece & " " & input.buffer_guid)
        'System.Threading.Thread.Sleep(10)
        Dim result As New getFilePieceOutput With {.buffer_piece = file_map(input.buffer_guid)(input.piece)}
        If input.piece + 1 = file_map(input.buffer_guid).Count Then
            file_map.Remove(input.buffer_guid)
        End If
        Return result
    End Function

    Public Function search(input As getSearchResultInput) As getSearchResultOutput
        Dim guids As New List(Of String)
        For Each c As IContent In cd.search(input.search)
            guids.Add(c.guid.ToString)
        Next
        Dim result As New getSearchResultOutput With {.guids = guids.ToArray}
        Return result
    End Function


End Class
